#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

#define nd(x) (nil + (x))

using namespace std;

const int lim = 1e9; 
const int N = 100010; 
const int lg = 60; 

struct node {
	int s; 
	node *lc, *rc; 
}; // 结构体，存储信息与左右儿子
node nil[N * lg], *rot[N]; 
int cnt; 

int n, m, a[N], dc[N]; 

node* insert(node *u, int l, int r, int p) { // 插入结点
	node *ret = ++cnt; // 新建结点
	*ret = *u, *ret->s ++; // 新建结点的初始值为原始结点
	if(l == r) return ret; // 叶子返回
	
	int mid = (l + r) / 2; 
	if(p <= mid) ret->lc = insert(ret  -> lc, l, mid, p); // 如果左儿子需要修改，则将左儿子赋值为更新后的结点
	else ret->rc = insert(ret -> rc, mid + 1, r, p); // 右儿子同理
	return ret; // 返回这个新增的结点
}

int query(node *u, node *v, int l, int r, int k) { // 二分查询第K大的值
	if(l == r) return dc[l]; 
	int mid = (l + r) / 2; 
	int c = u -> lc -> s - v -> lc -> s; // 在区间[L,R]中，值域在[l,mid]中的数的个数
	if(k <= c) return query(u -> lc, v -> lc, l, mid, k); // 在左边递归查找
	return query(u -> rc, v -> rc, mid + 1, r, k - c);  // 在右边递归查找
}

void read() {
	cin >> n >> m; 
	for(int i = 1; i <= n; i++) cin >> a[i]; 
}

void prep() { // 离散化操作
	for(int i=1; i<=n; i++) dc[i] = a[i];
	sort(dc+1, dc+n+1), dc[0] = unique(dc+1, dc+n+1) - dc - 1;
	for(int i=1; i<=n; i++) a[i] = lower_bound(dc+1, dc+dc[0]+1) - dc;
}

void solve() {
	cnt = nil->s = 0, rot[0] = nil->lc = nil->rc = nil;
	for(int i = 1; i <= n; i++) rot[i] = insert(rot[i-1], 1, dc[0], a[i]); // 初始化
	
	while(m--) {
		int l, r, k;
		cin >> l >> r >> k; 
		cout << query(rot[r], rot[l - 1], 1, dc[0], k) << endl; 
	}
}

int main() {
	read();
	prep();
	solve(); 
	return 0; 
}